Make HotSwap safe to concurrent access#3480
Conversation
| * For safer access to the current resource see [[get]], which guarantees that it will not be | ||
| * released while it is being used. | ||
| * | ||
| * If [[swap]] is called after the lifetime of the [[Hotswap]] is over, it will raise an | ||
| * error, but will ensure that all resources are finalized before returning. | ||
| */ | ||
| def swap(next: Resource[F, R]): F[R] |
There was a problem hiding this comment.
This API is a bit unsafey since it directly returns the R but I think we'll just have to live with that.
| /** | ||
| * Gets the current resource, if it exists. The returned resource is guaranteed to be | ||
| * available for the duration of the returned resource. | ||
| */ | ||
| def get: Resource[F, Option[R]] |
There was a problem hiding this comment.
Maybe a little bit annoying UX that this is an Option[R], alternatively we could raise an error. But the user can decide to do that too.
There was a problem hiding this comment.
Bikeshed the name. access a la HotswapRef ?
|
Woops, I didn't think this through :) we need to make sure that multiple readers don't block each other. h/t https://github.com/janstenpickle/hotswap-ref |
Co-authored-by: catostrophe <40268503+catostrophe@users.noreply.github.com>
| def shared: Resource[F, Unit] = semaphore.permit | ||
|
|
||
| def exclusive: Resource[F, Unit] = | ||
| Resource.makeFull[F, Unit](poll => poll(semaphore.acquireN(Long.MaxValue)))(_ => | ||
| semaphore.releaseN(Long.MaxValue)) |
There was a problem hiding this comment.
Stole this from here:
https://github.com/janstenpickle/hotswap-ref/blob/34781a0af15784981cd007b74f0f5c31836d73f3/modules/core/src/main/scala/io/janstenpickle/hotswapref/Lock.scala
It seems like a good addition to std on its own merits.
trait Lock[F[_]] {
def shared: Resource[F, Unit]
def exclusive: Resource[F, Unit]
}There was a problem hiding this comment.
There was a problem hiding this comment.
Lock would probably be a good addition, but the tricky bit is that it isn't reentrant, so we have to be really careful.
| def shared: Resource[F, Unit] = semaphore.permit | ||
|
|
||
| def exclusive: Resource[F, Unit] = | ||
| Resource.makeFull[F, Unit](poll => poll(semaphore.acquireN(Long.MaxValue)))(_ => | ||
| semaphore.releaseN(Long.MaxValue)) |
There was a problem hiding this comment.
Lock would probably be a good addition, but the tricky bit is that it isn't reentrant, so we have to be really careful.
Fixes #2050. Closes #3473.
The current resource in
Hotswapis now guarded by a mutex, which must be acquired to swap or clear it. A new methodgetalso provides safe access to the current resource, by acquiring the mutex while it is in use.